#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QSerialPortInfo>
#include <QMessageBox>
#include <QThread>
#include <cstring>
#include "data_proc.h"
#include <QTimer>
#include <QTimeZone>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    , is_opened(false)
{
    ui->setupUi(this);
    setWindowTitle("MLD预置设备RS422通信测试软件");

    mserial = new QSerialPort(this);
    serial_set();
    connect(mserial, &QSerialPort::readyRead, this, &Widget::read_data);
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        ui->comboBox->addItem(info.portName());
    }
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &Widget::dte_current_update);
    timer->start(1000);

    this->setWindowIcon(QIcon(":/img/port.png"));

    /*
    std::vector<uint8_t> data = {0xf4, 0x05, 0x02, 0x80, 0x43, 0x6d, 0x38};
    size_t length = data.size();
    uint16_t sum = 0;
    for (size_t i = 0; i < length; i++) {
        sum += data[i];
        printf(" 0x%02X ", data[i]);
    }
    printf("----------------------------------\n");
    std::pair<uint8_t, uint8_t> checksum = dp.calculateChecksum(data);
    printf("Checksum: 0x%02X\n", checksum.first);
    printf("Checksum: 0x%02X\n", checksum.second);
*/
    // 控件起始状态
    ui->pb_self_check->setEnabled(false);
    ui->pb_calibrate_time->setEnabled(false);
    ui->pb_input_parameter->setEnabled(false);
    ui->dateTimeEdit->setDisplayFormat("yyyy-MM-dd HH:mm:ss");
    ui->cb_selfcheck_watervoice->setEnabled(false);
    ui->cb_selfcheck_master->setEnabled(false);
    ui->cb_selfcheck_fuse->setEnabled(false);
    ui->dte_current->setDisplayFormat("yyyy-MM-dd HH:mm:ss");
    ui->dte_current->setEnabled(false);
    ui->cb_handshakestate->setEnabled(false);
    ui->te_show_text->setReadOnly(true);
    ui->cb_devicestate->setEnabled(false);
    ui->open_close->setStyleSheet(QString("QPushButton {"
                                          "color: white;"
                                          "background-color: #346636;"
                                          "}"));
    ui->pb_exit->setStyleSheet(QString("QPushButton {"
                                       "color: white;"
                                       "background-color: #e61100;"
                                       "}"));
    ui->cb_selfcheck_fuse->setEnabled(false);
    ui->cb_selfcheck_master->setEnabled(false);
    ui->cb_selfcheck_watervoice->setEnabled(false);
}

Widget::~Widget()
{
    if(is_opened)
    {
        serial_close();
    }
    delete ui;
}

void Widget::serial_set()
{
    mserial->setBaudRate(9600);//设置波特率
    mserial->setDataBits(QSerialPort::Data8);//设置数据位
    mserial->setStopBits(QSerialPort::OneStop);//停止位
    mserial->setParity(QSerialPort::NoParity);//无奇偶校验
    mserial->setFlowControl(QSerialPort::NoFlowControl);//无流控
}

bool Widget::serial_open()
{
    mserial->setPortName(ui->comboBox->currentText());
    return mserial->open(QIODevice::ReadWrite);
}
std::string Widget::read_data()
{
    QByteArray msg = mserial->readAll();

    QString hexDisplay;
    for (char byte : msg) {
        hexDisplay.append(QString::number(static_cast<unsigned char>(byte), 16).rightJustified(2, '0').toUpper());
        hexDisplay.append(" "); // 在每个字节后添加一个空格，以便于阅读
    }
    // 去除末尾可能存在的多余空格
    if (!hexDisplay.isEmpty()) {
        hexDisplay.chop(1);
    }
    ui->te_show_text->append("[R-0]收到信息为：" + hexDisplay);
    std::vector<uint8_t> msg_vec = dp.QByteArray2Vector(msg);
    qDebug() << "vec:" << msg_vec;
    std::pair<uint8_t, uint8_t> info_class = dp.getInfoFromReceived(msg_vec);
    qDebug() << "info_class:" << info_class;
    if(info_class.first < 0)
    {
        (info_class.second == 0)?(ui->te_show_text->append("[R-0]数据校验成功，但反馈类别未知！")):(ui->te_show_text->append("[R-0]数据校验失败！"));
    }
    switch (info_class.first) {
    case DATA_PROC::HandShakeRequst:
        recv_handshake(msg);
        break;
    case DATA_PROC::SelfCheckInfo:
        recv_selfcheck(msg);
        break;
    case DATA_PROC::InputParameter:
        recv_inputparameter(msg);
        break;
    case DATA_PROC::TimeAligned:
        recv_timealign(msg);
        break;
    default:
        break;
    }
    return msg.toStdString();
}

void Widget::write_data(const QByteArray &data)
{
    mserial->write(data);
}

void Widget::serial_close()
{
    mserial->close();
    ui->open_close->setText("open");
}

void Widget::recv_handshake(QByteArray &msg)
{
    std::vector<uint8_t> stand = {0xdd, 0xf0, 0x00, 0x10, 0x00, 0x0d, 0x0a};
    std::vector<uint8_t> recv = dp.QByteArray2Vector(msg);

    // 判断收到的信息是否为主控发送的握手信息
    for (size_t i = 0; i < stand.size(); i++) {
        if(stand[i] != recv[i])
        {
            ui->te_show_text->append("[R-1]该信息不是正确的握手信息！");
            return;
        }
    }
    ui->te_show_text->append("[R-1]收到来自主控正确的握手信息！");
    // 成功收到主控的握手请求，开始回复
    write_data(dp.data4responseHandShake());

    ui->te_show_text->append("[R-1]与主控握手成功！");
    ui->cb_handshakestate->setChecked(true);

}

void Widget::recv_selfcheck(QByteArray &msg)
{
    // eg:ddf30155b7fe0d0a
    ui->te_show_text->append("[R-2]收到来自主控正确的自检信息！");
    // 开始读取有效信息，判断自检状态
    uint8_t real_info = msg[3];
    // 提取高76，预留
    uint8_t bits76 = (real_info >> 6) & 0b11;
    // 提取高54，引信
    uint8_t bits54 = (real_info >> 4) & 0b11;
    // 提取低32，主控
    uint8_t bits32 = (real_info >> 2) & 0b11;
    // 提取低10, 水声
    uint8_t bits10 = real_info & 0b11;
    if (bits10 == 1)
    {
        ui->te_show_text->append("[R-2]水声模块自检状态完成！");
        ui->cb_selfcheck_watervoice->setChecked(true);
    }
    else
    {
        ui->te_show_text->append("[R-2]水声模块自检状态未完成！");
        ui->cb_selfcheck_watervoice->setChecked(false);
    }
    if (bits32 == 1)
    {
        ui->te_show_text->append("[R-2]主控自检状态完成！");
        ui->cb_selfcheck_master->setChecked(true);
    }
    else
    {
        ui->te_show_text->append("[R-2]主控自检状态未完成！");
        ui->cb_selfcheck_master->setChecked(false);
    }
    if (bits54 == 1)
    {
        ui->te_show_text->append("[R-2]引信自检状态完成！");
        ui->cb_selfcheck_fuse->setChecked(true);
    }
    else
    {
        ui->te_show_text->append("[R-2]引信模块自检状态未完成！");
        ui->cb_selfcheck_fuse->setChecked(false);
    }
}

void Widget::recv_inputparameter(QByteArray &msg)
{
    // eg.dd f5 01 12 f8 fe 0d 0a
    ui->te_show_text->append("[R-3]收到来自主控正确的设置参数反馈信息！");
    // 开始读取有效信息，判断设置状态
    uint8_t real_info = msg[3];
    switch (real_info) {
    case 0x10:
        ui->te_show_text->append("[R-3]时间装定失败！");
        break;
    case 0x11:
        ui->te_show_text->append("[R-3]成功装定相对时间！");
        break;
    case 0x12:
        ui->te_show_text->append("[R-3]成功装定绝对时间！");
        break;
    default:
        break;
    }
}

void Widget::recv_timealign(QByteArray &msg)
{
    // eg. dd f7 01 11 f7 fe 0d 0a
    ui->te_show_text->append("[R-4]收到来自主控正确的时间校准信息！");
    uint8_t real_info = msg[3];
    switch (real_info) {

    case 0x11:
        ui->te_show_text->append("[R-4]时间装定成功！");
        break;
    case 0x12:
        ui->te_show_text->append("[R-4]时间装定失败！");
        break;
    default:
        break;
    }
}


/*
 * 打开关闭按钮
 */
void Widget::on_open_close_clicked()
{
    if(is_opened)
    {
        serial_close();
        qDebug()<<"串口关闭成功";
        ui->te_show_text->append("[Local]串口关闭成功");
        ui->cb_devicestate->setChecked(false);
        is_opened = false;
        ui->open_close->setStyleSheet(QString("QPushButton {"
                                              "color: white;"
                                              "background-color: #346636;"
                                              "}"));
        ui->cb_handshakestate->setChecked(false);
    }
    else
    {
        if(serial_open())
        {
            qDebug()<<"串口打开成功";
            ui->te_show_text->append("[Local]串口打开成功");
            ui->cb_devicestate->setChecked(true);
            ui->open_close->setText("close");
            is_opened = true;

            ui->open_close->setStyleSheet(QString("QPushButton {"
                                                  "color: white;"
                                                  "background-color: #E61100;"
                                                  "}"));
        }
        else
        {
            qDebug()<<"串口打开失败";
            QMessageBox::information(this, "Info", "串口打开失败");
            ui->te_show_text->append("[Local]串口打开失败");
            is_opened = false;
        }
    }
}
/*
 * 退出程序按钮
 */
void Widget::on_pb_exit_clicked()
{
    this->close();
}

void Widget::on_pb_self_check_clicked()
{
    write_data(dp.data4selfCheckInfo());
}

void Widget::on_rb_absolute_time_clicked()
{
    ui->dateTimeEdit->setEnabled(true);
    ui->le_time_second->setEnabled(false);
    ui->rb_relative_time->setChecked(false);
}

void Widget::on_rb_relative_time_clicked()
{
    ui->dateTimeEdit->setEnabled(false);
    ui->le_time_second->setEnabled(true);
    ui->rb_absolute_time->setChecked(false);
}

void Widget::on_pb_input_parameter_clicked()
{
    QDateTime g_currentTime = ui->dte_current->dateTime();
    QDateTime g_utcDateTime = g_currentTime.toUTC();
    qint64 g_unixTime = g_utcDateTime.toSecsSinceEpoch();


    if(!ui->rb_absolute_time->isChecked() && !ui->rb_relative_time->isChecked())
    {
        QMessageBox::information(this, "Info", "请先设置有效的时间！");
        return;
    }
    bool isRelative = false;
    uint32_t time = 0;

    // 设置相对时间
    if(ui->rb_relative_time->isChecked())
    {
        isRelative = true;
        time = ui->le_time_second->text().toUInt();
        QDateTime currentTime = QDateTime::currentDateTime();
        if(time <= 0)
        {
            QMessageBox::information(this, "Info", "请输入一个大于0的整数！");
            return ;
        }

        ui->te_show_text->append("[T-3]设置相对时间：" + QString::number(time) + "秒！预计北京时间："
                                 + QDateTime::fromTime_t(static_cast<time_t>(g_unixTime + time)).toString("yyyy-MM-dd HH:mm:ss"));
    }
    // 设置绝对时间
    else
    {
        isRelative = false;
        QDateTime dateTime = ui->dateTimeEdit->dateTime();
        QDateTime utcDateTime = dateTime.toUTC();
        qint64 unixTime = utcDateTime.toSecsSinceEpoch();

        if (unixTime > static_cast<qint64>(std::numeric_limits<uint32_t>::max())) {
             ui->te_show_text->append("[T-3]Timestamp too large for uint32_t");
        } else {
            time = static_cast<uint32_t>(unixTime);
            ui->te_show_text->append("[T-3]设置绝对（北京）时间："
                                     + QDateTime::fromTime_t(static_cast<time_t>(time)).toString("yyyy-MM-dd HH:mm:ss")
                                     + " Unix时间戳：" + QString::number(time));
        }
    }
    write_data(dp.data4inputPresetParameter(isRelative, time));

}

void Widget::on_pb_calibrate_time_clicked()
{

    QDateTime currentTime = ui->dte_current->dateTime();
    QDateTime utcDateTime = currentTime.toUTC();
    qint64 unixTime = utcDateTime.toSecsSinceEpoch();

    uint32_t time = 0;
    // 32位的Unix时间戳（注意2038年溢出问题）
    if (unixTime > static_cast<qint64>(std::numeric_limits<uint32_t>::max())) {
         ui->te_show_text->append("[T-4]Timestamp too large for uint32_t");
    } else {
        time = static_cast<uint32_t>(unixTime);
        ui->te_show_text->append("[T-4]北京时间校准：" + currentTime.toString("yyyy-MM-dd HH:mm:ss"));
    }
    write_data(dp.data4timeAlign(time));

}

void Widget::dte_current_update()
{
    QDateTime currentTime = QDateTime::currentDateTime();
    ui->dte_current->setDateTime(currentTime);

}

void Widget::on_cb_handshakestate_stateChanged(int arg1)
{
    if(arg1 == 0)
    {
        ui->pb_self_check->setEnabled(false);
        ui->pb_self_check->setStyleSheet(QString("QPushButton {"
                                                 "color: gray;"
                                                 "background-color: #eeeeee;"
                                                 "}"));
        ui->pb_calibrate_time->setEnabled(false);
        ui->pb_calibrate_time->setStyleSheet(QString("QPushButton {"
                                                       "color: gray;"
                                                       "background-color: #eeeeee;"
                                                       "}"));
        ui->pb_input_parameter->setEnabled(false);
        ui->pb_input_parameter->setStyleSheet(QString("QPushButton {"
                                                         "color: gray;"
                                                         "background-color: #eeeeee;"
                                                         "}"));
    }
    else
    {
        ui->pb_self_check->setEnabled(true);
        ui->pb_self_check->setStyleSheet(QString("QPushButton {"
                                                 "color: white;"
                                                 "background-color: #346636;"
                                                 "}"));
        ui->pb_input_parameter->setEnabled(true);
        ui->pb_input_parameter->setStyleSheet(QString("QPushButton {"
                                                        "color: white;"
                                                        "background-color: #346636;"
                                                        "}"));
        ui->pb_calibrate_time->setEnabled(true);
        ui->pb_calibrate_time->setStyleSheet(QString("QPushButton {"
                                                     "color: white;"
                                                     "background-color: #346636;"
                                                     "}"));
    }
}
